package com.yz.jdd.module.launch.view;


import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.gyf.barlibrary.ImmersionBar;
import com.tencent.smtt.sdk.QbSdk;
import com.tonyodev.fetch2.AbstractFetchListener;
import com.tonyodev.fetch2.Download;
import com.tonyodev.fetch2.Error;
import com.tonyodev.fetch2.Fetch;
import com.tonyodev.fetch2.FetchConfiguration;
import com.tonyodev.fetch2.FetchListener;
import com.tonyodev.fetch2.NetworkType;
import com.tonyodev.fetch2.Priority;
import com.tonyodev.fetch2.Request;
import com.tonyodev.fetch2okhttp.OkHttpDownloader;
import com.trello.rxlifecycle.ActivityEvent;
import com.yz.jdd.GuideActivity;
import com.yz.jdd.R;
import com.yz.jdd.base.MyApplication;
import com.yz.jdd.base.activity.BaseActivity;
import com.yz.jdd.base.event.Events;
import com.yz.jdd.base.event.RxBus;
import com.yz.jdd.base.utils.AppUtils;
import com.yz.jdd.base.utils.BaseConfigs;
import com.yz.jdd.base.utils.Constants;
import com.yz.jdd.base.utils.IDUtil;
import com.yz.jdd.base.utils.LogUtils;
import com.yz.jdd.base.utils.MD5Util;
import com.yz.jdd.base.utils.PreferencesUtils;
import com.yz.jdd.module.launch.model.AppVersion;
import com.yz.jdd.module.launch.model.H5Module;
import com.yz.jdd.module.launch.presenter.DeviceLoginPresenter;
import com.yz.jdd.module.login.view.LoginActivity;
import com.yz.jdd.module.main.MainActivity;
import com.yz.jdd.module.privacy.PrivacyCallback;
import com.yz.jdd.module.privacy.PrivacyDialog;
import com.yz.jdd.module.privacy.ProtocolInfo;
import com.yz.jdd.module.privacy.ProtocolResult;
import com.yz.jdd.module.upgrade.DownLoadDialogActivity;
import com.yz.jdd.webview.download.H5DownFileUtils;
import com.yz.jdd.widget.PublicDialog;

import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

public class LaunchActivity extends BaseActivity implements DeviceLoginView {
    private DeviceLoginPresenter presenter;

    public static LaunchActivity instance = null;

    Fetch fetch;
    TextView text_loading;
    ProgressBar progressBar;
    private final ArrayMap<Integer, Integer> fileProgressMap = new ArrayMap<>();

    /**
     * 已经下载的H5Module
     */
    private Map<String, H5Module> downLoadModels = new HashMap();

    public static final int MSG_UNZIPDOWN = 0;
    public static final int MSG_SHOWLOADING = 1;
    /**
     * h5版本map
     */
    Map<String, String> jsonMap = new HashMap<>();
    private final Handler myHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (MSG_UNZIPDOWN == msg.what) {
                unzipDownload();
            } else {
                if (MSG_SHOWLOADING == msg.what) {
                    text_loading.setText("加载中...");
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().setBackgroundDrawable(null);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        instance = this;
        super.onCreate(savedInstanceState);
        if (!isTaskRoot()) {
            finish();
            return;
        }

        drawFlag();
        setContentView(R.layout.activity_launch);

        ImmersionBar.with(this).reset()
                .transparentStatusBar()  //透明状态栏，不写默认透明色
                .transparentNavigationBar()  //透明导航栏，不写默认黑色(设置此方法，fullScreen()方法自动为true)
                .transparentBar().init();


        boolean isAgreed = PreferencesUtils.getBoolean(MyApplication.application, Constants.PREF_PRIVACY_AGREED, false);
        if (isAgreed) {
            launch();
        } else {
            showPrivacy();
        }
    }

    /**
     * 隐私协议提示弹窗
     */
    public void showPrivacy() {
        new PrivacyDialog.Builder()
                .activity(LaunchActivity.this)
                .protocolResult(ProtocolResult.obtain(ProtocolInfo.TYPE_POLICY))
                .callback(new PrivacyCallback() {
                    @Override
                    public void onAgree() {
                        PreferencesUtils.putBoolean(MyApplication.application, Constants.PREF_PRIVACY_AGREED, true);
                        launch();
                    }

                    @Override
                    public void onDisagree() {
                        showPrivacySecond();
                    }
                })
                .build()
                .show();
    }


    private void launch() {


        QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

            @Override
            public void onViewInitFinished(boolean arg0) {
                // TODO Auto-generated method stub
                //x5內核初始化完成的回调，为true表示x5内核加载成功，否则表示x5内核加载失败，会自动切换到系统内核。

                LogUtils.e("=== onViewInitFinished is " + arg0);
            }

            @Override
            public void onCoreInitFinished() {
                // TODO Auto-generated method stub
            }
        };
        //x5内核初始化接口
        QbSdk.initX5Environment(getApplicationContext(), cb);

        presenter = new DeviceLoginPresenter(this);
        initEventBus();

        closeAndroidPDialog();
        initFetch();
        presenter.deviceLogin();


    }

    /**
     * 初始化事件监听
     */
    private void initEventBus() {
        RxBus.with(this).setEvent(Events.EVENT_CONNECTION_SUCCESS).setEndEvent(ActivityEvent.DESTROY).onNext(new Action1<Events<?>>() {
            @Override
            public void call(Events<?> events) {
                dismissLoading();
                presenter.deviceLogin();

            }
        }).create();
        RxBus.with(this).setEvent(Events.EVENT_PERMISSION_SUCCESS).setEndEvent(ActivityEvent.DESTROY).onNext(new Action1<Events<?>>() {
            @Override
            public void call(Events<?> events) {
                presenter.checkNetworkInfo();

            }
        }).create();
    }

    /**
     * 初始化下载引擎
     */
    private void initFetch() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .build();

        FetchConfiguration fetchConfiguration;
        fetchConfiguration = new FetchConfiguration.Builder(this)
                .setDownloadConcurrentLimit(3)
                .setHttpDownloader(new OkHttpDownloader(okHttpClient))
                .setAutoRetryMaxAttempts(1)
                .build();
        setUpViews();
        fetch = Fetch.Impl.getInstance(fetchConfiguration);
        reset();
    }


    private void setUpViews() {
        text_loading = findViewById(R.id.text_loading);
        progressBar = findViewById(R.id.progressBar);
    }

    private void reset() {

        fetch.deleteAll();

        fileProgressMap.clear();

        progressBar.setProgress(0);

        text_loading.setText("加载中...");

    }

    /**
     * 通过反射关闭9.0弹窗
     */
    private void closeAndroidPDialog() {
        try {
            Class aClass = Class.forName("android.content.pm.PackageParser$Package");
            Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Class cls = Class.forName("android.app.ActivityThread");
            Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
            declaredMethod.setAccessible(true);
            Object activityThread = declaredMethod.invoke(null);
            Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
            mHiddenApiWarningShown.setAccessible(true);
            mHiddenApiWarningShown.setBoolean(activityThread, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void onClickToExit(View v) {
        LogUtils.e("=== onClickToExit");
        secondDialog.dismiss();
        finish();
    }

    public void onClickToAgree(View v) {
        LogUtils.e("=== onClickToAgree");
        secondDialog.dismiss();
        showPrivacy();
    }

    private Dialog secondDialog;

    public void showPrivacySecond() {
        String str = "我们需要获得您对《用户协议》和《隐私政策》的同意后，才能继续为您提供服务";
        final View inflate = LayoutInflater.from(LaunchActivity.this).inflate(R.layout.dialog_privacy_second, null);
        TextView tv_content = (TextView) inflate.findViewById(R.id.tv_content);
        tv_content.setText(str);
        secondDialog = new AlertDialog
                .Builder(LaunchActivity.this)
                .setView(inflate)
                .show();
        // 通过WindowManager获取
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        final WindowManager.LayoutParams params = secondDialog.getWindow().getAttributes();
        params.gravity = Gravity.CENTER;
        params.width = dm.widthPixels * 5 / 6;
        params.height = dm.heightPixels * 1 / 3;
        secondDialog.setCancelable(false);

        secondDialog.getWindow().setAttributes(params);
        secondDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
    }

    @Override
    public void setAppVersion(AppVersion appVersion, String autoLogin) {
    }

    @Override
    public void copyAssert() {
        try {
            H5DownFileUtils.copyAssetsFile(LaunchActivity.this);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void show() {

    }

    @Override
    public void startLoginActivity() {
        boolean showGuide = PreferencesUtils.getBoolean(MyApplication.application, Constants.PRE_SHOW_GUIDE, true);
        LogUtils.d("--- startLoginActivity showGuide="+showGuide);
        if (showGuide){
            Intent intent = new Intent(LaunchActivity.this, GuideActivity.class);
            startActivity(intent);
        }else{
            Intent intent = new Intent(LaunchActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    }


    @Override
    public String isFirstLogin() {

        return PreferencesUtils.getString(this, BaseConfigs.BOOLEAN_FIRSTTIME,
                "true");
    }

    @Override
    public String getIMEI() {
        String deviceId = PreferencesUtils.getString(MyApplication.application, Constants.PREF_ANDROID_ID, "");
        if (TextUtils.isEmpty(deviceId)) {
            deviceId = IDUtil.getDeviceUUID(this);
        }
        PreferencesUtils.putString(MyApplication.application, Constants.PREF_ANDROID_ID, deviceId);
        return deviceId;

    }

    @Override
    public String getAppVersion() {
        return AppUtils.getVerName(this);
    }

    @Override
    public String getNetWorkType() {
        return AppUtils.getNetWorkType(this);
    }

    @Override
    public String getLon() {
        return PreferencesUtils.getString(this, BaseConfigs.STRING_LON,
                "0");
    }

    @Override
    public String getLat() {
        return PreferencesUtils.getString(this, BaseConfigs.STRING_LAT,
                "0");
    }

    @Override
    public String getSysVersion() {
        return AppUtils.getSDKVersion() + "";
    }

    @Override
    public String getDeviceModel() {
        return AppUtils.getDeviceInfo();
    }

    @Override
    public String getGUID() {
        return PreferencesUtils.getString(this, BaseConfigs.STRING_GUID,
                "");
    }


    @Override
    public void startMainActivity() {
        Intent intent = new Intent(LaunchActivity.this, MainActivity.class);
        String main_url = "file://" + H5DownFileUtils._UPZIP_FOLDERPATH + "vuepages/index.html#/?s=" +
                PreferencesUtils.getString(this, BaseConfigs.PREF_SESSIONID) +
                "&statusBarHeight=0&android=4.1" + "&SDK=" + Build.VERSION.SDK_INT
                + "&url=" + PreferencesUtils.getString(LaunchActivity.this, BaseConfigs.STRING_SERVER_URL, Constants.SERVER_URL);
        intent.putExtra(Constants.H5_WEB_URL, main_url);
        startActivity(intent);
    }

    @Override
    public void close() {

        finish();


    }

    @Override
    public void showErrorDialog(String msg) {
        final PublicDialog publicDialog = new PublicDialog(this);
        publicDialog.setMessage(msg);

        publicDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) {
                if (i == KeyEvent.KEYCODE_BACK) {
                    finish();
                }
                return false;
            }
        });
        publicDialog.setRightBtn("取消",
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        publicDialog.dismiss();
                        finish();

                    }
                });
        publicDialog.setLeftBtn("重试", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                presenter.checkNetworkInfo();
                publicDialog.dismiss();

            }
        });
        publicDialog.show();
    }

    /**
     * 计算下载完成的文件个数
     *
     * @return
     */
    private int getCompletedFileCount() {
        int count = 0;
        final Set<Integer> ids = fileProgressMap.keySet();
        for (int id : ids) {
            int progress = fileProgressMap.get(id);
            if (progress == 100) {
                count++;
            }
        }
        return count;
    }

    /**
     * 获取下载进度
     *
     * @return
     */
    private int getDownloadProgress() {
        int currentProgress = 0;
        final int totalProgress = fileProgressMap.size() * 100;
        final Set<Integer> ids = fileProgressMap.keySet();
        for (int id : ids) {
            currentProgress += fileProgressMap.get(id);
        }
        currentProgress = (int) (((double) currentProgress / (double) totalProgress) * 100);
        return currentProgress;
    }

    /**
     * 更新UI
     */
    private void updateUIWithProgress() {

        final int totalFiles = fileProgressMap.size();
        final int completedFiles = getCompletedFileCount();
        LogUtils.e("=== totalFiles : " + totalFiles + "--completedFiles: " + completedFiles);
        text_loading.setText("加载中...");

        final int progress = getDownloadProgress();
        progressBar.setProgress(progress);
        if (completedFiles == totalFiles) {
            LogUtils.e( "=== updateUIWithProgress");
            //全部下载完成去解压
            myHandler.sendEmptyMessageDelayed(MSG_UNZIPDOWN, 1000);
        }
    }

    /**
     * 下载H5
     *
     * @param h5Module
     */
    @Override
    public void downLoadH5Model(List<H5Module> h5Module) {
        if (h5Module != null && h5Module.size() > 0) {
            progressBar.setVisibility(View.VISIBLE);
            text_loading.setVisibility(View.VISIBLE);

            List<Request> requests = new ArrayList<>();
            for (H5Module model : h5Module) {

                String zipUrl = model.getAddress();
                String fileName = model.getName() + ".zip";
                try {
                    URL mUrl = new URL(zipUrl);
                    fileName = new File(mUrl.getFile()).getName();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                String filePath = H5DownFileUtils._ZIP_FOLDERPATH + fileName;
                Request request = new Request(zipUrl, filePath);
                request.setPriority(Priority.HIGH);
                request.setNetworkType(NetworkType.ALL);

                requests.add(request);
                fileProgressMap.put(request.getId(), 0);
                Log.e("jindd", "unzipPath=" + filePath);
                model.setUnzipPath(filePath);
                downLoadModels.put(zipUrl, model);

                H5DownFileUtils.downLoadFile(zipUrl, filePath, new H5DownFileUtils.OnDownloadListener() {
                    @Override
                    public void onProgress(int progress) {
                        myHandler.obtainMessage(MSG_SHOWLOADING);
                        progressBar.setProgress(progress);
                    }

                    @Override
                    public void onError(String errorMessage) {
                        LogUtils.e("=== H5资源包下载失败：" + errorMessage);
                    }

                    @Override
                    public void onComplete() {
                        //全部下载完成去解压
                        myHandler.sendEmptyMessageDelayed(0, 1000);
                    }
                });
            }
        } else {
            progressBar.setVisibility(View.GONE);
        }
    }

    /**
     * 下载监听器
     */
    private FetchListener fetchListener = new AbstractFetchListener() {
        @Override
        public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {
            super.onProgress(download, etaInMilliSeconds, downloadedBytesPerSecond);
            Log.d("jindd", "Progress: " + download.getProgress());
            fileProgressMap.put(download.getId(), download.getProgress());
            updateUIWithProgress();
        }

        @Override
        public void onError(Download download, Error error, Throwable throwable) {
            super.onError(download, error, throwable);
        }

        @Override
        public void onCompleted(@NotNull Download download) {
            Log.e("jindd", "download Completed " + download.getUrl() + "download path " + download.getFile());
            fileProgressMap.put(download.getId(), download.getProgress());

        }
    };

    /**
     * 解压H5
     */
    private void unzipDownload() {
        LogUtils.e("=== unzipDownload");
        //取出本地
        String localVersion = PreferencesUtils.getString(MyApplication.application, BaseConfigs.PREFS_STR_H5, "");
        LogUtils.e("=== localVersion : " + localVersion);


        if (!TextUtils.isEmpty(localVersion)) {
            Gson gson = new Gson();
            jsonMap = gson.fromJson(localVersion, new TypeToken<Map<String, String>>() {
            }.getType());
        }
        //缓存已经解压的
        final Map<String, String> unzipModels = new HashMap<>();

        Observable.from(downLoadModels.values())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Subscriber<H5Module>() {
                    @Override
                    public void onCompleted() {
                        LogUtils.e( "=== unzip  onCompleted");
                        if (unzipModels.size() == downLoadModels.values().size()) {
                            //全部解压成功
                            Gson gson = new Gson();
                            String jsonStr = gson.toJson(jsonMap);
                            LogUtils.Log("lkf", "put=" + jsonStr);
                            PreferencesUtils.putString(
                                    LaunchActivity.this.getApplicationContext(),
                                    BaseConfigs.PREFS_STR_H5, jsonStr);
                            presenter.showVersionUpdate();
                        } else {
                            LogUtils.e( "=== 解压失败");
                        }

                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        LogUtils.e("=== unzip onError : " + e.toString());
                    }

                    @Override
                    public void onNext(H5Module model) {
                        //取出压缩包地址,解压
                        File zipFile = new File(model.getUnzipPath());
                        LogUtils.e("=== filePath:" + model.getUnzipPath());
                        //取出已下载文件的md5
                        String modelMD5 = MD5Util.getFileMD5(zipFile);
                        LogUtils.e(zipFile.exists() + "modelMD5==" + modelMD5 + "serverMd5==" + model.getHashcode());
                        if (true) {
                            //md5相同执行解压新的
                            boolean upZipSuccess = H5DownFileUtils.upZipFile(zipFile, H5DownFileUtils._UPZIP_FOLDERPATH, "");
                            if (upZipSuccess) {
                                //解压成功,删掉zip
                                unzipModels.put(model.getName(), model.getVersion());
                                jsonMap.put(model.getName(), model.getVersion());
                            }
                        } else {
                            //MD5 不同就删掉
                            if (zipFile != null && zipFile.exists()) {
                                zipFile.delete();
                                //这里可以执行一下showToast
                                LogUtils.e( "=== modelMD5 : " + modelMD5 + "serverMd5==" + model.getHashcode());

                            }
                        }
                        LogUtils.e("onNext==" + model.getName() + "---upZipSuccess=" + model.getVersion());
                    }
                });
    }


    @Override
    public void showVersionUpdate(AppVersion appVersion, final String url, final String autoLogin) {
        if (appVersion != null) {
            if (!"true".equals(appVersion.getForceUpdate())) {
                Long timeStap = System.currentTimeMillis() - PreferencesUtils.getLong(LaunchActivity.this, BaseConfigs.LONG_TIMESTAP);
                if (timeStap < 24 * 3600000) {
                    if ("true".equals(autoLogin)) {
                        startMainActivity();
                        close();
                    } else {
                        startLoginActivity();
                        close();
                    }
                    return;
                }
            }
            Intent intentDown = new Intent(LaunchActivity.this, DownLoadDialogActivity.class);
            intentDown.putExtra("url", url);
            intentDown.putExtra("autoLogin", autoLogin);
            intentDown.putExtra("appVersion", appVersion);
            startActivity(intentDown);
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (fetch != null) {
            fetch.addListener(fetchListener);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (fetch != null) {
            fetch.removeListener(fetchListener);
        }
    }

    @Override
    protected void onDestroy() {
        if (fetch != null) {
            fetch.close();
        }
        super.onDestroy();
    }
}
